package com.share.common.utils;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.core.DefaultParameterNameDiscoverer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * @author 01401061 - 孙艳强
 * @date 2020/11/21 16:49
 */
public class ClassUtil {
    /**
     * 获取方法的  返回值的class类全路径，如果是基础数据类型的则直接跳过
     *
     * @param method
     * @return
     */
    /*public static java.util.List<java.util.Map<java.lang.String, java.lang.Integer>> com.share.common.utils.ClassUtil.tess(java.lang.Class<?>)*/
    public static List<String> listAllReturnTypeClass(Method method) {
        List<String> relist = new LinkedList<>();
        if (method == null) {
            return relist;
        }
        String methodSign = method.toGenericString();
        int kh1 = methodSign.lastIndexOf("(");
        String str = methodSign.substring(0, methodSign.lastIndexOf(" ", kh1));
        int start = methodSign.lastIndexOf(" ", methodSign.indexOf("."));
        String returnTypeSign = str.substring(start).trim().replace(" ", "");

        String[] split = returnTypeSign.split("[<,>]");
        for (String path : split) {
            if (path == null) {
                continue;
            } else if ("".equals(path)) { /*无返回值的类型*/
                continue;
            } else if ("?".equals(path)) {
                /*Result<?>*/
                continue;
            } else if (path.startsWith("?extends")) {
                /*Result<Page<? extends UserInfo>>*/
                relist.add(path.replace("?extends", ""));
                continue;
            } else {
                relist.add(path);
            }
        }
        return relist;
    }

    /**
     * 获取某个类的泛型
     * interface A<T, ID>  或者  class A<T, ID>
     * class B implements A<String, Integer>
     *
     * @param clazz
     * @return
     */
    public static Class<?>[] getActualTypeArgument(Class<?> clazz) {
        Type genericSuperclass = clazz.getGenericSuperclass();
        return getActualTypeArgument(genericSuperclass);
    }

    /**
     * 获取某个类的泛型
     * interface A<T, ID>  或者  class A<T, ID>
     * class B implements A<String, Integer>
     *
     * @param clazz
     * @return
     */
    public static Class<?>[] getActualTypeArgument(Type genericSuperclass) {
        Class<?> entitiClass[] = null;
        if (genericSuperclass instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass)
                    .getActualTypeArguments();
            if (actualTypeArguments != null && actualTypeArguments.length > 0) {
                int size = actualTypeArguments.length;
                entitiClass = new Class[size];
                for (int i = 0; i < size; i++) {
                    entitiClass[i] = (Class<?>) actualTypeArguments[i];
                }
            }
        }
        return entitiClass;
    }


    /**
     * 获取到对象的所有字段（包括所有继承的父类）
     * Class.getFields();  当前类或者父类的  public属性
     * Class.getDeclaredFields();  当前类所有属性
     *
     * @param clazz
     * @return
     */
    public static List<Field> getAllDeclaredFields(final Class clazz) {
        List<Field> fields = new ArrayList<>();
        Class tmpClazz = clazz;
        while (tmpClazz != null && tmpClazz != Object.class) {
            fields.addAll(Arrays.asList(tmpClazz.getDeclaredFields()));
            tmpClazz = tmpClazz.getSuperclass();
        }
        return fields;
    }

    /**
     * 获取指定类指定方法的参数名
     * isImplicit() 这个属性值表示编译的时候是否修改变量名
     */
    public static String[] getMethodParameterNames(Method method) {
        /*spring提供的获取参数变量名的工具了*/
        DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        if (discoverer != null) {
            discoverer.getParameterNames(method);
        }
        return null;
    }

    /**
     * 获取这个类的所有父类
     *
     * @param clazz
     * @return
     */
    public static List<Class<?>> listSuperClass(Class<?> clazz) {
        List<Class<?>> clazzList = new ArrayList<Class<?>>(3);
        Class<?> supClazz = clazz.getSuperclass();
        while (supClazz != null) {
            clazzList.add(supClazz);
            supClazz = supClazz.getSuperclass();
        }
        return clazzList;
    }

    /**
     * 获取这个类的所有接口
     *
     * @param clazz
     * @return
     */
    public static List<Class<?>> listSuperInterfaces(Class<?> clazz) {
        List<Class<?>> clazzList = new ArrayList<>(3);
        Class<?>[] supClazzList = clazz.getInterfaces();
        if (ArrayUtils.isEmpty(supClazzList)) {
            return clazzList;
        }

        for (Class<?> interfaceClass : supClazzList) {
            //添加自己
            clazzList.add(interfaceClass);

            //添加父类的父类并递归
            List<Class<?>> tmpList = listSuperInterfaces(interfaceClass);
            clazzList.addAll(tmpList);
        }
        return clazzList;
    }

    public static void main(String[] args) {
        try {
            Method dateToStr = DateUtil.class.getMethod("dateToStr", Date.class, String.class);
            String[] parameterNames2 = getMethodParameterNames(dateToStr);
            System.out.println(new String(String.valueOf(parameterNames2)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
